#pragma once
#include "../page/db_page.h"
#include "../catalog/catalog_manager.h"

class BPlusTree
{
public:
    BPlusTree(const std::string &table_name, const std::string &index_name, CatalogManager &catalog_manager);

    // 公开的插入接口
    void Insert(const BPlusTreeKey &key, const Row &row, CatalogManager &catalog_manager_);

    void Insert(const BPlusTreeKey &key, const BPlusTreeKey &value, CatalogManager &catalog_manager);

    uint32_t Delete(const BPlusTreeKey &key, CatalogManager &catalog_manager_);

    uint32_t Delete(const BPlusTreeKey &key, const BPlusTreeKey &value, CatalogManager &catalog_manager_);

    uint32_t DeleteRange(const BPlusTreeKey &start_key, const BPlusTreeKey &end_key, CatalogManager &catalog_manager_);

    uint32_t DeleteAll(CatalogManager &catalog_manager_);
    /**
     * @brief 单点查询：根据键查找单条记录。
     * @param key 要查找的键。
     * @param[out] row 如果找到，用于存储结果行的引用。
     * @return bool 如果找到记录则返回 true，否则返回 false。
     */
    bool Search(const BPlusTreeKey &key, Row &row);
    bool SearchForSecondary(const BPlusTreeKey &key, std::vector<BPlusTreeKey> &values);

    /**
     * @brief 范围查询：查找一个闭区间 [start_key, end_key] 内的所有记录。
     * @param start_key 范围的起始键。
     * @param end_key 范围的结束键。
     * @return std::vector<Row> 包含所有符合条件的行的向量。
     */
    std::variant<std::vector<Row>, std::vector<BPlusTreeKey>> SearchRange(const BPlusTreeKey &start_key, const BPlusTreeKey &end_key,bool left_inclusive = true, bool right_inclusive = true);

    /**
     * @brief 全表扫描：获取表中的所有记录。
     * @return std::vector<Row> 包含表中所有行的向量。
     */
    std::variant<std::vector<Row>, std::vector<BPlusTreeKey>> ScanAll();

    uint32_t Update(const BPlusTreeKey &key, const std::unordered_map<std::string, Value> &new_values, CatalogManager &catalog_manager_);
    uint32_t UpdateRange(const BPlusTreeKey &start_key, const BPlusTreeKey &end_key, const std::unordered_map<std::string, Value> &new_values, CatalogManager &catalog_manager_);
    uint32_t UpdateAll(const std::unordered_map<std::string, Value> &new_values, CatalogManager &catalog_manager_);
    void Print();
    bool isEmpty(){
        return root_page_id_ == INVALID_PAGE_ID;
    }
private:
    std::string table_name_;
    std::string index_name_;
    uint32_t root_page_id_;
    bool is_primary_;
    Logger&logger_;
    // 内部递归插入函数
    // 返回 std::optional<{key, page_id}> 表示是否需要向上层插入新的键值对
    std::optional<std::pair<BPlusTreeKey, uint32_t>> InsertInternal(DBPage *page, const BPlusTreeKey &key, const std::variant<Row, BPlusTreeKey> &value);

    // 统一的分裂函数
    std::pair<BPlusTreeKey, uint32_t> SplitPage(DBPage *page);
    void updateRootPageId(uint32_t new_root_id, CatalogManager &catalog_manager);

    uint32_t DeleteInternal(DBPage *parent_page, uint32_t current_page_id, const BPlusTreeKey &key, const BPlusTreeKey *value_ptr, CatalogManager &catalog_manager);
    void HandleUnderflow(DBPage *parent_page, DBPage *underflow_page);

    uint32_t UpdateInternal(DBPage *page, int index, const std::unordered_map<std::string, Value> &new_values, CatalogManager &catalog_manager_);

    void Redistribute(DBPage *sibling_page, DBPage *page_in_need, DBPage *parent_page, int index_in_parent, bool is_left_sibling = true);
    void Merge(DBPage *parent_page, uint32_t left_page_id, uint32_t right_page_id, int index_in_parent);
    void PrintRecursive(uint32_t page_id, int level, bool is_last);

    std::unique_ptr<DBPage> FindLeafPage(const BPlusTreeKey &key);

    uint32_t findFirstLeafPageId();
    void updateChildrenParent(DBPage *parent_page, int start_index, int end_index);

    std::unique_ptr<DBPage> getPage(uint32_t page_id);
};